package org.thanos.simulator;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

public class DragAndDropCanvas extends JFrame {

    private final CanvasPanel canvasPanel;
    private final List<DraggableShape> shapes = new ArrayList<>();
    private DraggableShape selectedShape;
    private Point dragOffset;
    private JLabel statusBar;
    private JPopupMenu contextMenu;

    public DragAndDropCanvas() {
        setTitle("Java Swing 拖拽画布 (带边界限制和右键删除)");
        setSize(900, 650);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // 创建状态栏
        statusBar = new JLabel("就绪");
        statusBar.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
        add(statusBar, BorderLayout.SOUTH);

        // 创建工具栏
        JToolBar toolBar = createToolBar();
        add(toolBar, BorderLayout.NORTH);

        // 左侧拖拽元素面板
        JPanel leftPanel = createLeftPanel();

        // 右侧画布区域
        canvasPanel = new CanvasPanel();
        canvasPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));

        // 添加组件到主窗口
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, new JScrollPane(canvasPanel));
        splitPane.setDividerLocation(150);
        add(splitPane, BorderLayout.CENTER);

        // 创建右键菜单
        createContextMenu();

        setLocationRelativeTo(null);
    }

    private void createContextMenu() {
        contextMenu = new JPopupMenu();
        JMenuItem deleteItem = new JMenuItem("删除");
        deleteItem.addActionListener(e -> {
            if (selectedShape != null) {
                shapes.remove(selectedShape);
                canvasPanel.repaint();
                updateStatus("已删除: " + selectedShape.type);
                selectedShape = null;
            }
        });
        contextMenu.add(deleteItem);
    }

    private JToolBar createToolBar() {
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);

        JButton clearBtn = new JButton("清空画布");
        clearBtn.addActionListener(e -> {
            shapes.clear();
            canvasPanel.repaint();
            updateStatus("画布已清空");
        });

        JButton saveBtn = new JButton("保存");
        saveBtn.addActionListener(e -> {
            updateStatus("保存功能未实现");
        });

        toolBar.add(clearBtn);
        toolBar.addSeparator();
        toolBar.add(saveBtn);

        return toolBar;
    }

    private JPanel createLeftPanel() {
        JPanel leftPanel = new JPanel();
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
        leftPanel.setBorder(BorderFactory.createTitledBorder("拖拽元素"));
        leftPanel.setPreferredSize(new Dimension(150, 0));
        leftPanel.setBackground(new Color(240, 240, 240));

        // 创建可拖拽的形状
        String[] shapeNames = {"矩形", "圆形", "三角形", "星形", "箭头"};
        Color[] colors = {
                new Color(135, 206, 235),    // 矩形 - 天蓝色
                new Color(255, 182, 193),     // 圆形 - 粉红色
                new Color(152, 251, 152),     // 三角形 - 浅绿色
                new Color(255, 215, 0),       // 星形 - 金色
                new Color(221, 160, 221)      // 箭头 - 紫罗兰色
        };

        for (int i = 0; i < shapeNames.length; i++) {
            DraggableComponent comp = new DraggableComponent(shapeNames[i], colors[i]);
            leftPanel.add(comp);
            leftPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        }

        return leftPanel;
    }

    private void updateStatus(String message) {
        statusBar.setText(message);
    }

    // 可拖拽的组件
    class DraggableComponent extends JLabel {
        public DraggableComponent(String text, Color color) {
            super(text);
            setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
            setOpaque(true);
            setBackground(color);
            setPreferredSize(new Dimension(120, 40));
            setHorizontalAlignment(SwingConstants.CENTER);
            setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

            // 设置拖拽源
            DragSource dragSource = DragSource.getDefaultDragSource();
            dragSource.createDefaultDragGestureRecognizer(
                    this, DnDConstants.ACTION_COPY, new DragGestureHandler());
        }

        // 拖拽手势处理器
        class DragGestureHandler implements DragGestureListener {
            @Override
            public void dragGestureRecognized(DragGestureEvent dge) {
                Transferable transferable = new StringSelection(getText());
                dge.startDrag(null, transferable);
                updateStatus("拖拽中: " + getText());
            }
        }
    }

    // 画布面板
    class CanvasPanel extends JPanel implements DropTargetListener, MouseListener, MouseMotionListener {
        public CanvasPanel() {
            setBackground(Color.WHITE);
            new DropTarget(this, DnDConstants.ACTION_COPY, this, true);
            addMouseListener(this);
            addMouseMotionListener(this);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 绘制网格背景
            drawGridBackground(g2d);

            // 绘制所有已放置的形状
            for (DraggableShape shape : shapes) {
                g2d.setColor(shape.color);

                if (shape == selectedShape) {
                    // 绘制选中状态边框
                    g2d.setStroke(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
                            1.0f, new float[]{5, 5}, 0));
                    g2d.setColor(Color.BLUE);
                    g2d.drawRect(shape.x - 5, shape.y - 5, shape.width + 10, shape.height + 10);
                    g2d.setStroke(new BasicStroke(2));
                }

                // 绘制形状
                g2d.setColor(shape.color);
                if ("矩形".equals(shape.type)) {
                    g2d.fillRect(shape.x, shape.y, shape.width, shape.height);
                } else if ("圆形".equals(shape.type)) {
                    g2d.fillOval(shape.x, shape.y, shape.width, shape.height);
                } else if ("三角形".equals(shape.type)) {
                    int[] xPoints = {shape.x + shape.width/2, shape.x, shape.x + shape.width};
                    int[] yPoints = {shape.y, shape.y + shape.height, shape.y + shape.height};
                    g2d.fillPolygon(xPoints, yPoints, 3);
                } else if ("星形".equals(shape.type)) {
                    drawStar(g2d, shape.x + shape.width/2, shape.y + shape.height/2,
                            shape.width/2, shape.height/2, 5);
                } else if ("箭头".equals(shape.type)) {
                    drawArrow(g2d, shape.x, shape.y, shape.width, shape.height);
                }

                // 绘制文字标签
                g2d.setColor(Color.BLACK);
                FontMetrics fm = g2d.getFontMetrics();
                Rectangle2D bounds = fm.getStringBounds(shape.type, g2d);
                int textX = shape.x + (shape.width - (int)bounds.getWidth())/2;
                int textY = shape.y + (shape.height + fm.getAscent())/2;
                g2d.drawString(shape.type, textX, textY);
            }

            // 绘制边界限制提示
            g2d.setColor(new Color(255, 0, 0, 100));
            g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
        }

        private void drawGridBackground(Graphics2D g2d) {
            int gridSize = 20;
            g2d.setColor(new Color(245, 245, 245));

            for (int x = 0; x < getWidth(); x += gridSize) {
                g2d.drawLine(x, 0, x, getHeight());
            }

            for (int y = 0; y < getHeight(); y += gridSize) {
                g2d.drawLine(0, y, getWidth(), y);
            }
        }

        private void drawStar(Graphics2D g2d, int centerX, int centerY, int radius1, int radius2, int points) {
            int[] xPoints = new int[points * 2];
            int[] yPoints = new int[points * 2];

            double angle = Math.PI / points;

            for (int i = 0; i < points * 2; i++) {
                double r = (i % 2 == 0) ? radius1 : radius2;
                double theta = i * angle;
                xPoints[i] = centerX + (int)(r * Math.cos(theta));
                yPoints[i] = centerY + (int)(r * Math.sin(theta));
            }

            g2d.fillPolygon(xPoints, yPoints, points * 2);
        }

        private void drawArrow(Graphics2D g2d, int x, int y, int width, int height) {
            int[] xPoints = {x, x + width, x + width - 20, x + width, x + width - 20, x};
            int[] yPoints = {y + height/2, y + height/2, y, y + height/2, y + height, y + height/2};
            g2d.fillPolygon(xPoints, yPoints, 6);
        }

        // 拖拽进入时调用
        @Override
        public void dragEnter(DropTargetDragEvent dtde) {
            dtde.acceptDrag(DnDConstants.ACTION_COPY);
        }

        // 拖拽结束时调用
        @Override
        public void drop(DropTargetDropEvent dtde) {
            try {
                Transferable transferable = dtde.getTransferable();
                if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                    dtde.acceptDrop(DnDConstants.ACTION_COPY);
                    String data = (String) transferable.getTransferData(DataFlavor.stringFlavor);

                    // 获取鼠标位置并创建新形状
                    Point dropPoint = dtde.getLocation();

                    // 创建新形状并应用边界限制
                    DraggableShape newShape = new DraggableShape(data, dropPoint.x, dropPoint.y);
                    constrainToBounds(newShape);

                    shapes.add(newShape);

                    dtde.dropComplete(true);
                    repaint();
                    updateStatus("已添加: " + data);
                    return;
                }
                dtde.rejectDrop();
            } catch (Exception ex) {
                ex.printStackTrace();
                dtde.rejectDrop();
            }
        }

        // 鼠标按下事件 - 选择形状
        @Override
        public void mousePressed(MouseEvent e) {
            // 检查是否点击了某个形状
            for (int i = shapes.size() - 1; i >= 0; i--) {
                DraggableShape shape = shapes.get(i);
                if (shape.contains(e.getX(), e.getY())) {
                    selectedShape = shape;
                    dragOffset = new Point(e.getX() - shape.x, e.getY() - shape.y);
                    updateStatus("选中: " + shape.type);
                    repaint();

                    // 如果是右键点击，显示上下文菜单
                    if (SwingUtilities.isRightMouseButton(e)) {
                        contextMenu.show(this, e.getX(), e.getY());
                    }
                    return;
                }
            }
            selectedShape = null;

            // 在空白处右键点击，清除选择
            if (SwingUtilities.isRightMouseButton(e)) {
                repaint(); // 清除任何选择状态
            }
        }

        // 鼠标拖拽事件 - 移动形状（带边界限制）
        @Override
        public void mouseDragged(MouseEvent e) {
            if (selectedShape != null && SwingUtilities.isLeftMouseButton(e)) {
                // 计算新位置
                int newX = e.getX() - dragOffset.x;
                int newY = e.getY() - dragOffset.y;

                // 应用边界限制
                selectedShape.x = Math.max(0, Math.min(newX, getWidth() - selectedShape.width));
                selectedShape.y = Math.max(0, Math.min(newY, getHeight() - selectedShape.height));

                repaint();
            }
        }

        // 鼠标释放事件 - 取消选择
        @Override
        public void mouseReleased(MouseEvent e) {
            if (selectedShape != null && SwingUtilities.isLeftMouseButton(e)) {
                updateStatus("已移动: " + selectedShape.type);
            }
        }

        // 确保形状在画布边界内
        private void constrainToBounds(DraggableShape shape) {
            shape.x = Math.max(0, Math.min(shape.x, getWidth() - shape.width));
            shape.y = Math.max(0, Math.min(shape.y, getHeight() - shape.height));
        }

        // 以下方法需要实现但不需要具体内容
        @Override public void dragOver(DropTargetDragEvent dtde) {}
        @Override public void dropActionChanged(DropTargetDragEvent dtde) {}
        @Override public void dragExit(DropTargetEvent dte) {}
        @Override public void mouseClicked(MouseEvent e) {}
        @Override public void mouseEntered(MouseEvent e) {}
        @Override public void mouseExited(MouseEvent e) {}
        @Override public void mouseMoved(MouseEvent e) {}
    }

    // 表示可拖拽形状的类
    static class DraggableShape {
        String type;
        int x, y;
        int width = 80;
        int height = 60;
        Color color;

        public DraggableShape(String type, int dropX, int dropY) {
            this.type = type;
            this.x = dropX - width/2; // 居中显示
            this.y = dropY - height/2;

            // 为不同类型设置不同颜色
            if ("矩形".equals(type)) color = new Color(135, 206, 235);
            else if ("圆形".equals(type)) color = new Color(255, 182, 193);
            else if ("三角形".equals(type)) color = new Color(152, 251, 152);
            else if ("星形".equals(type)) color = new Color(255, 215, 0);
            else color = new Color(221, 160, 221); // 箭头
        }

        public boolean contains(int pointX, int pointY) {
            return pointX >= x && pointX <= x + width &&
                    pointY >= y && pointY <= y + height;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            DragAndDropCanvas frame = new DragAndDropCanvas();
            frame.setVisible(true);
        });
    }
}